home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Grab Bag
/
Shareware Grab Bag.iso
/
007
/
vtkerma1.arc
/
MSCMD.ASM
next >
Wrap
Assembly Source File
|
1986-02-13
|
37KB
|
1,311 lines
PAGE 59, 132
TITLE MSCMD -- COMND module for MS-Kermit
; Update 22 Jan 86
IF1
%OUT >> Starting pass 1
ELSE
%OUT >> Starting pass 2
ENDIF
; This version has machine-dependent code for both IBM PCs and DEC Rainbows
PUBLIC comnd, cmcfrm, prserr, repars, cmgtch, drives, comand, fcbcpy
INCLUDE MsDefs.H
DataS SEGMENT PUBLIC 'DataS'
extrn flags:byte, trans:byte, fcb:byte, DTA:byte
extrn taklev:byte, takadr:word, dosnum:byte, OldStk:WORD
EXTRN PC_Type:BYTE, In_menu_mode:BYTE
comand cmdinfo <>
cmer00 DB '? Program error Invalid COMND call',cr,lf,'$'
cmer01 DB '? Ambiguous',cr,lf,'$'
cmer02 DB '? Illegal input file spec',cr,lf,'$'
cmer03 DB '? Invalid command',cr,lf,'$'
cmer04 DB '? Invalid command or operand',cr,lf,'$'
cmer06 DB '? Wildcard not allowed',cr,lf,'$'
cmer07 DB '? Invalid drive specificaton',cr,lf,'$'
cmin00 DB ' Confirm with carriage return$'
cmin01 DB ' One of the following:',cr,lf,'$'
F5_str DB '<F5>',cr,lf,'$'
DO_str DB '<Do>',cr,lf,'$'
cmthlp DW 0 ; Text of help message for random input
drives DB 0 ; How many drives we have. [21a]
crlf DB cr,lf,'$'
ctcmsg DB '^C', Cr, Lf, '$'
prsp DB ' $' ; Print a space
hlpmsg DW 0 ; Address of help message
spchar DB 24H,26H,23H,40H,21H,25H,27H,28H,29H,2DH
DB 3CH,3EH,7BH,7DH,5FH,5CH,5EH,7EH,7CH,60H
spclen equ $-spchar
spchar2 DB 24H,26H,23H,40H,21H,25H,27H,28H,29H,2DH
DB 7BH,7DH,5FH,5EH,7EH,60H
spc2len equ $-spchar2
escspc DB 10O,' ',10O,'$' ; Clear escape
clrspc DB ' ',10O,'$' ; Clear space
filbuf DB 60H DUP(?) ; Character buffer
tbuff DB 80 DUP(?)
cmdstk DW ?
; Parallel tables used to turn keypad function keys into binary ASCII values
Sensible_func_keys db 2fh,32h,35h,38h,3bh,3eh,41h,44h,47h,4ah,4dh,50h,53h,56h
To_ASCII_scan_codes db 30h,31h,32h,33h,34h,35h,36h,37h,38h,39h,2dh,2ch,2eh,0dh
Func_table_length EQU $ - To_ASCII_scan_codes
DataS ENDS
Code SEGMENT PUBLIC
extrn dodel:near, ctlu:near, cmblnk:near, locate:near, takrd:near
extrn clearl:near, KrmRet:NEAR, Telnet2:NEAR, Beep:NEAR
EXTRN Quick_Push:NEAR, Quick_Menu:NEAR
assume cs:code,ds:datas,es:datas
; This routine parses the specified function in AH. Any additional
; information is in DX and BX
; Returns +1 on success
; +4 on failure (assumes a JMP follows the call)
CMND PROC NEAR
comnd: mov comand.cmstat,ah ; Save what we are presently parsing
mov cmdstk,sp ; save stack ptr locally
call cminbf ; Get chars until an action or a erase char
mov ah,comand.cmstat ; Restore 'ah' for upcoming checks
cmp ah,cmcfm ; Parse a confirm?
jz cmcfrm ; Go get one
cmp ah,cmkey ; Parse a keyword?
jnz cm1
jmp cmkeyw ; Try and get one
cm1: cmp ah,cmifi ; Parse an input file spec?
jnz cm2
jmp cmifil ; Go get one
cm2: cmp ah,cmofi ; Output file spec?
jnz cm3
jmp cmofil ; Go get one
cm3: cmp ah,cmtxt ; Parse arbitrary text. [8]
jnz cm4
jmp cmtext
cm4: mov ah,prstr ; Else give error
mov dx,offset cmer00 ; "?Unrecognized COMND call"
int dos
ret
; This routine gets a confirm
cmcfrm: call cmgtch ; Get a char
cmp ah,0 ; Is it negative (a terminator; a space or
; a tab will not be returned here as they
; will be seen as leading white space.)
js cmcfr0
ret ; If not, return failure
cmcfr0: and ah,7FH ; Turn off the minus bit
cmp ah,esc ; Is it an escape?
jne cmcfr2
mov ah,conout
mov dl,bell ; Get a bell
int dos
mov ah,0
mov comand.cmaflg,ah ; Turn off the action flag
mov bx,comand.cmcptr ; Move the pointer to before thee scape
dec bx
mov comand.cmcptr,bx
mov comand.cmdptr,bx
dec comand.cmccnt ; Decremrnt the char count
jmp cmcfrm ; Try again
cmcfr2: cmp ah,'?' ; Curious?
jne cmcfr3
mov ah,prstr ; Print something useful
mov dx,offset cmin00
int dos
mov ah,prstr
mov dx,offset crlf ; Print a crlf
int dos
mov ah,prstr
mov dx,comand.cmprmp ; Reprint the prompt
int dos
mov bx,comand.cmdptr ; Get the pointer into the buffer
mov ah,'$' ; Put a $ there for printing
mov [bx],ah
mov bx,comand.cmcptr
dec bx ; Decrement & save the buffer pointer
mov comand.cmcptr,bx
mov ah,prstr
mov dx,offset comand.cmdbuf
int dos
mov ah,0 ; Turn off the action flag
mov comand.cmaflg,ah
jmp repars ; Reparse everything
cmcfr3: cmp ah,ff ; Is it a form feed?
jne cmcfr4
call cmblnk ; If so blank the screen
cmcfr4: jmp rskp
; This routine parses a keyword from the table pointed
; to in DX. The format of the table is as follows:
;
; addr: DB n ; Where n is the # of entries in the table
; DB m ; M is the size of the keyword
; DB 'string$' ; Where string is the keyword
; DW ab ; Where ab is data to be returned
;
; The keywords must be in alphabetical order
cmkeyw: mov comand.cmhlp,bx ; Save the help
mov comand.cmptab,dx ; Save the beginning of keyword table
mov bx,dx
mov ch,[bx] ; Get number of entries in table
inc bx
mov dx,comand.cmdptr ; Save command pointer
mov comand.cmsptr,dx ; Save pointer's here
cmky1: cmp ch,0 ; Any commands left to check?
jne cmky2
jmp cmky41 ; no, go complain
cmky2: dec ch
mov cl,0 ; Keep track of how many chars read in so far
call cmgtch ; Get a char
cmp ah,0 ; Do we have a terminator?
jns cmky2x
jmp cmky4 ; Negative number means we do
cmky2x: inc bx ; Point to first letter of keyword
inc cl ; Read in another char
mov al,[bx]
cmp ah,'a' ; Less than a?
jl cmky21 ; If so, don't capitalize
cmp ah,'z'+1 ; More than z?
jns cmky21
and ah,137O ; Capitalize the letter
cmky21: cmp ah,al
je cmky3
jg cmky2y
jmp cmky41 ; Fail if ah preceeds al alphabetically
cmky2y: jmp cmky6 ; Not this keyword - try the next
cmky3: inc bx ; We match here, how 'bout next char?
mov al,[bx]
cmp al,'$' ; End of keyword?
jne cmky3x
jmp cmky7 ; Succeed
cmky3x: mov dl,al ; Save al's char here
call cmgtch
inc cl ; Read in another char
mov al,dl
cmp ah,'a'
jl cmky31
cmp ah,'z'+1
jns cmky31
and ah,137O
cmky31: cmp ah,esc+80H ; Escape Recognition (escape w/minus bit on)?
je cmky3y
cmp ah,'?'+80H ; A question mark? [3]
je cmky3y
cmp ah,' '+80H ; A space?
je cmky3y
cmp ah,cr+80H ; Carriage return?
je cmky3y
jmp cmky38
cmky3y: mov comand.cmkptr,bx ; Save bx here
mov comand.cmsiz,cx ; Save size info
mov comand.cmchr,ah ; Save char for latter
call cmambg ; See if input is ambiguous or not
jmp cmky32 ; Succeeded (not ambiguous)
mov ah,comand.cmchr
cmp ah,esc+80H ; Escape?
je cmky3z
cmp ah,'?'+80H ; maybe question mark?
je cmkyj1 ; yes, go handle
jmp cmky41 ; Else fail
cmky3z: mov ah,conout ; Ring a bell
mov dl,bell
int dos
mov bx,comand.cmcptr ; Move pointer to before the escape
dec bx
mov comand.cmcptr,bx
mov comand.cmdptr,bx
dec comand.cmccnt ; Decrement char count
mov bx,comand.cmkptr ; Failed - pretend user never typed ...
mov cx,comand.cmsiz ; ... in a char
dec cl ; Don't count the escape
dec bx
mov comand.cmaflg,0 ; Reset the action flag
jmp cmky3 ; Keep checking
; ambiguous. Print out all the keywords that match
cmkyj1: mov dx,offset cmin01
mov ah,prstr
int dos
mov bx,comand.cmkptr ; this is current keyword
mov cx,comand.cmsiz ; we are cl chars into it
mov ch,0
sub bx,cx ; back up to beginning
inc bx ; not counting ?
mov comand.cmkptr,bx ; save beginning of kw
cmkyj2: mov dl,tab ; put a tab before each keyword
mov ah,conout
int dos
mov dx,comand.cmkptr ; get current keyword
mov ah,prstr
int dos ; print it
mov bx,comand.cmkptr ; get keyword back
dec bx
mov al,[bx] ; get length
mov ah,0
add ax,5 ; skip length, $, value, next length
add bx,ax ; this is next keyword
mov si,bx
mov di,comand.cmkptr ; compare with last keyword
mov comand.cmkptr,bx ; update this
mov cx,comand.cmsiz
dec ch ; are we at end of table?
jl cmkyj3 ; yes, don't go on
mov comand.cmsiz,cx ; else update count
mov ch,0
dec cl ; this includes ?
jcxz cmkyj2 ; empty, just print it
repe cmpsb ; compare to previous string
je cmkyj2 ; same, go print this one
cmkyj3: jmp cmky50 ; else go finish up
cmky32: mov cx,comand.cmsiz ; Restore info
mov bx,comand.cmkptr ; Our place in the keyword table
cmp comand.cmchr,0A0H ; Space?
je cmky35
cmp comand.cmchr,0BFH ; Question mark? [3]
je cmky35
cmp comand.cmchr,8DH ; Carriage return?
je cmky35
dec comand.cmcptr ; Pointer into buffer of input
mov dx,comand.cmcptr
cmky33: mov ah,[bx] ; Get next char in keyword
cmp ah,'$' ; Are we done yet?
jz cmky34
mov di,dx
mov [di],ah
inc bx
inc dx
inc comand.cmccnt
jmp cmky33
cmky34: mov ah,' '
mov di,dx
mov [di],ah ; Put a blank in the buffer
inc dx
mov cx,comand.cmcptr ; Remember where we were
mov comand.cmcptr,dx ; Update our pointers
mov comand.cmdptr,dx
mov ah,'$'
mov di,dx
mov [di],ah ; Add '$' for printing
mov ah,prstr
mov dx,cx ; Point to beginning of filled in data
int dos
inc bx ; Point to address we'll need
mov bx,[bx]
mov comand.cmaflg,0 ; Turn off action flag
jmp rskp
cmky35: inc bx
mov ah,[bx] ; Find end of keyword.
cmp ah,'$'
jne cmky35
inc bx
mov bx,[bx] ; Address of next routine to call
; mov comand.cmaflg,0 ; Zero the action flag
jmp rskp
cmky38: cmp ah,al
je cmky39
jmp cmky6 ; Go to end of keyword and try next
cmky39: jmp cmky3 ; Check next letter
cmky4: and ah,7FH ; Turn off minus bit
cmp ah,'?' ; Need help?
je cmky5
cmp ah,' ' ; Just a space - no error
je cmky51
cmp ah,cr
je cmky51
cmp ah,tab
je cmky51
cmp ah,esc ; Ignore escape?
je cmky43
cmky41: mov ah,prstr
mov dx,offset cmer03
int dos
jmp prserr ; Parse error - give up
cmky43: mov ah,conout ; Ring a bell
mov dl,bell
int dos
mov bx,comand.cmcptr
dec bx
mov comand.cmcptr,bx
mov comand.cmdptr,bx
dec comand.cmccnt ; Don't count the escape
mov comand.cmaflg,0 ; Reset action flag
inc ch ; Account for a previous 'dec'
jmp cmky1 ; Start over
cmky5: inc bx ; point to actual keyword
mov comand.cmkptr,bx ; remember current kw
mov cl,1 ; code above expects to count ?
mov comand.cmsiz,cx ; and size
mov dx,comand.cmhlp
or dx,dx ; was any help given?
jnz cmky5a ; yes, use it
jmp cmkyj1 ; else make our own message
cmky5a: mov ah,prstr
int dos
cmky50: mov ah,prstr
mov dx,offset crlf
int dos
mov dx,comand.cmprmp ; Address of prompt
int dos
mov bx,comand.cmdptr ; Get pointer into buffer
mov al,'$'
mov [bx],al ; Add dollar sign for printing
mov dx,offset comand.cmdbuf
int dos
dec comand.cmcptr ; Don't keep it in the buffer
dec comand.cmccnt ; Don't conut it
mov comand.cmaflg,0 ; Turn off the action flag
jmp repars
cmky51: cmp comand.cmcr,1 ; Are bare CR's allowed?
je cmky52 ; Yes
mov ah,prstr
mov dx,offset cmer04 ; Complain
int dos
cmky52: jmp prserr
cmky6: inc bx ; Find end of keyword
mov al,[bx]
cmp al,'$'
jne cmky6
inc bx ; Beginning of next command
inc bx
inc bx
mov dx,comand.cmsptr ; Get old cmdptr
mov comand.cmdptr,dx ; Restore
mov comand.cmsflg,0FFH
jmp cmky1 ; Keep trying
cmky7: call cmgtch ; Get char
cmp ah,0
js cmky71 ; Ok if a terminator
dec bx
jmp cmky6 ; No match - try next keyword
cmky71: inc bx ; Get necessary data
mov bx,[bx]
cmp ah,9BH ; An escape?
jne cmky72
mov ah,prstr
mov dx,offset prsp ; Print a space
int dos
mov di,comand.cmcptr
dec di
mov ah,20H
mov [di],ah ; Replace escape char with space
mov comand.cmaflg,0
mov comand.cmsflg,0FFH ; Pretend they typed a space
cmky72: jmp rskp
; See if keyword is unambiguous or not from what the user has typed in
cmambg: cmp ch,0 ; Any keywords left to check?
jne cmamb0
ret ; If not then not ambiguous
cmamb0: inc bx ; Go to end of keyword ..
mov al,[bx] ; So we can check the next one
cmp al,'$'
jne cmamb0
add bx,4 ; Point to start of next keyword
dec cl ; Don't count escape
mov dx,comand.cmsptr ; Buffer with input typed by user
cmamb1: mov ah,[bx] ; Keyword char.
mov di,dx
mov al,[di] ; Input char
cmp al,'a' ; Do capitalizing
jl cmam11
cmp al,'z'+1
jns cmam11
and al,137O
cmam11: cmp ah,al ; Keyword bigger than input (alphabetically)?
jle cmamb2 ; No - keep checking
ret ; Yes - not ambiguous
cmamb2: inc bx ; Advance one char
inc dx
dec cl
jnz cmamb1
jmp rskp ; Fail - it's ambiguous
cmifil: mov hlpmsg,bx ; Address of help message
mov bx,dx ; Get the fcb address in bx
mov comand.cmfcb,bx ; Save it
mov ch,0 ; Initialize char count
mov ah,0
mov [bx],ah ; Set the drive to default to current
inc bx
mov comand.cmfcb2,bx
mov cl,' '
cmifi0: mov [bx],cl ; Blank the FCB
inc bx
inc ah
cmp ah,0BH ; Twelve?
jl cmifi0
cmifi1: call cmgtch ; Get another char
cmp ah,0 ; Is it an action character
js cmif1x ; Jump out of range. [21a]
jmp cmifi2 ; Ditto. [21a]
cmif1x: and ah,7FH ; Turn off the action bit. [21a]
cmp ah,'?' ; A question mark?
jne cmif12
mov al,0
mov comand.cmaflg,al ; Blank the action flag
dec comand.cmcptr ; Decrement the buffer pointer
dec comand.cmccnt ; Decrement count
mov ah,prstr
mov dx,hlpmsg ; Help message
int dos
mov dx,offset crlf
int dos
mov dx,comand.cmprmp
int dos
mov bx,comand.cmdptr
mov al,'$'
mov [bx],al ; Put in dollar sign for printing
mov dx,offset comand.cmdbuf
int dos
jmp repars
cmif12: cmp ah,esc ; An escape?
je cm12x
jmp cmif13
cm12x: mov comand.cmaflg,0 ; Turn off the action flag
dec comand.cmcptr ; Move pointers to before the escape
dec comand.cmdptr
dec comand.cmccnt ; Decrement char count
mov comand.cmchr,ch ; Save current character count
cmp ch,9 ; Past '.'?
jl cmf120 ; No
dec ch ; Yes, don't count point
cmf120: mov di,comand.cmfcb2 ; Fill the rest with CP/M wildcards
mov ah,'?'
cmf121: cmp ch,11 ; Done?
jge cmf122 ; Yes
mov [di],ah
inc di
inc ch
jmp cmf121
cmf122: mov ah,sfirst ; Find first matching file?
mov dx,comand.cmfcb ;[jd] use pointer to PASSED fcb
int dos
cmp al,0FFH ; Any found?
jne cmf123 ; Yes
jmp cmf12b ; No, lose
cmf123: mov di,offset filbuf ; Copy first file spec from DTA to buffer
mov bx,offset DTA+1
mov cl,11
call fcbcpy
mov di,offset filbuf+10H ; Get another copy (if not ambiguous)
mov bx,offset DTA+1
mov cl,11
call fcbcpy
mov ah,snext ; More matching specs?
mov dx,comand.cmfcb ;[jd] use PASSED fcb..
int dos
cmp al,0FFH
je cmf124 ; Only one
mov di,offset filbuf+10H ; Copy second file spec
mov bx,offset DTA+1
mov cl,11
call fcbcpy
cmf124: mov si,offset filbuf ; Start comparing file names
mov bx,offset filbuf+10H
mov di,comand.cmcptr ; Command buffer pointer
mov cl,comand.cmchr ; Bypass characters typed
cmp cl,9 ; Past '.'?
jl cmf125 ; No
dec cl ; Yes, don't count point
cmf125: mov ch,0 ; Adjust pointers
add si,cx
add bx,cx
mov ch,cl ; Update character count
cmf126: cmp ch,11 ; All done?
jne cmf127 ; No
jmp cmf12a ; Yes
cmf127: cmp ch,8 ; End of file name?
jne cmf128 ; No
cmp comand.cmchr,9 ; Exactly at point?
je cmf128 ; Yes, don't output a second point
mov ah,'.' ; Output separator
mov [di],ah
inc di
inc comand.cmccnt
cmf128: mov ah,[si] ; Get a character from first file spec
inc si
mov al,[bx] ; Get another from second spec
inc bx
cmp ah,al ; Compare
jne cmf12a ; Ambiguous
inc ch ; Same, count
cmp ah,' ' ; Blank?
je cmf129 ; Yes, don't output
mov [di],ah
inc di
inc comand.cmccnt
cmf129: jmp cmf126 ; Repeat
%OUT >> About half way through source file
cmf12a: mov comand.cmchr,ch ; Save count of characters processed
mov ah,'$' ; Put terminator into buffer
mov [di],ah
mov comand.cmcptr,di ; Save pointer for recognized characters
mov ah,prstr
mov dx,comand.cmdptr
int dos
mov ch,comand.cmchr ; Characters processed
cmp ch,11 ; Complete file name
je cmf12c ; Yes, don't beep
cmf12b: mov ah,conout ; Beep, if not recognized
mov dl,bell
int dos ; Ring the bell
cmf12c: jmp repars
cmif13: mov ah,ch ; It must be a terminator
cmp ah,0 ; Test the length of the file name
jnz cmf3x
cmp comand.cmcr,1 ; Is zero length OK? [21a]
je cmf3z ; Return successfully. [21a]
jmp cmifi9 ; If zero complain
cmf3x: cmp ah,0DH
js cmf3y
jmp cmifi9 ; If too long complain
cmf3y: jmp rskp ; Otherwise we have succeeded
cmf3z: push es
mov ax,ds
mov es,ax
mov di,comand.cmfcb
inc di
mov cx,11
mov al,'?'
repne stosb
pop es
mov flags.wldflg,0FFH ; Remember we had a wildcard
jmp rskp
cmifi2: cmp ah,'.'
jne cmifi3
inc ch
mov ah,ch
cmp ah,1H ; Any chars yet?
jnz cmf2x
jmp cmifi9 ; No, give error
cmf2x: cmp ah,0AH ; Tenth char?
js cmf2y
jmp cmifi9 ; Past it, give an error
cmf2y: mov dl,9H
mov dh,0
mov bx,comand.cmfcb
add bx,dx ; Point to file type field
mov comand.cmfcb2,bx
mov ch,9H ; Say we've gotten nine
jmp cmifi1 ; Get the next char
cmifi3: cmp ah,':'
jne cmifi4
inc ch
cmp ch,2H ; Is it in right place for a drive?
je cmif3x
jmp cmifi9 ; If not, complain
cmif3x: mov ch,0 ; Reset char count
mov flags.droflg,1 ; Override default drive. [21a]
mov flags.nmoflg,0 ; Not so fast. [21a]
mov bx,comand.cmfcb2
mov al,':' ; Use for parsing drive name
mov [bx],al
dec bx ; Point to drive spec
mov si,bx
push es
mov ax,ds
mov es,ax
mov di,offset tbuff ; Borrow this buffer
mov ah,prsfcb
int dos
pop es
cmp al,0 ; OK return code?
je cmif3y ; Yes, keep going
; mov ah,[bx] ; Get the drive name
; sub ah,'@' ; Get the drive number
; cmp ah,drives ; Did user specify a non-existant drive? [21a]
; jle cmif3y ; Nope, so continue. [21a]
mov dx,offset cmer07 ; Fail with this error message. [21a]
jmp cmif9x ; [21a]
cmif3y: mov comand.cmfcb2,bx ; Put rest of filename starting here. [21a]
mov ah,[bx] ; Pick up drive specified
sub ah,'@' ; Get real value
mov bx,comand.cmfcb
mov [bx],ah ; Put it in the fcb
push bx
mov al,' ' ; Overwrite the drive and ":"
inc bx
mov [bx],al
inc bx
mov [bx],al
pop bx
jmp cmifi1
cmifi4: cmp ah,'*'
jne cmifi7
cmp comand.cmrflg,1 ; In receive mode? [21a]
jne cmif4x ; Jump out of range. [21a]
mov dx,offset cmer06 ; Set the error message. [21a]
jmp cmif9x ; Fail - no wildcard allowed. [21a]
cmif4x: mov ah,ch ; [21a]
cmp ah,8H ; Is this in the name or type field?
jns cmifi5 ; Type
mov cl,8H ; Say we have eight chars
js cmifi6 ; Name field
jmp cmifi9 ; If its where the dot should be give up
cmifi5: mov cl,0CH ; Three chars
cmifi6: mov flags.wldflg,0FFH ; Remember we had a wildcard
mov bx,comand.cmfcb2 ; Get a pointer into the FCB
mov ah,'?'
mov [bx],ah ; Put a question mark in
inc bx
mov comand.cmfcb2,bx
inc ch
mov ah,ch
cmp ah,cl
jl cmifi6 ; Go fill in another
jmp cmifi1 ; Get the next char
cmifi7: cmp ah,03DH ; Equals sign (wildcard)?
jne cmif7x
cmp comand.cmrflg,1 ; In receive mode? [21a]
jne cmif7y ; No, so it's ok. [21a]
mov dx,offset cmer06 ; Set the error message. [21a]
jmp cmif9x ; Fail - no wildcard allowed. [21a]
cmif7y: mov ah,'?' ; New label. [21a]
mov flags.wldflg,0FFH ; Say we have a wildcard
jmp cmifi8 ; Put into FCB
cmif7x: cmp ah,'0'
jl cmif8x
cmp ah,'z'+1
jns cmif8x
cmp ah,'A' ; Don't capitalize non-alphabetics
jl cmifi8
and ah,137O ; Capitalize
cmifi8: mov bx,comand.cmfcb2 ; Get the pointer into the FCB
mov [bx],ah ; Put the char there
inc bx
mov comand.cmfcb2,bx
mov flags.nmoflg,1 ; Overriding name from host. [21a]
inc ch
jmp cmifi1
cmif8x: push es
mov cx,ds
mov es,cx ; Scan uses ES register
mov di,offset spchar ; Special chars
mov cx,spclen ; How many of them
cmp dosnum,0 ; Under version 2.0
je cmif8y
mov di,offset spchar2
mov cx,spc2len
cmif8y: mov al,ah ; Char is in al
repnz scasb ; Search string for input char
cmp cx,0 ; Was it there?
pop es
jnz cmifi8
cmifi9: mov dx,offset cmer02
cmif9x: mov ah,prstr
int dos
mov flags.droflg,0 ; Not overriding drive. [21a]
mov flags.nmoflg,0 ; Or name to save file under. [21a]
mov comand.cmrflg,0 ; Reset this flag too. [21a]
ret
cmofil: jmp cmifil ; For now, the same as CMIFI
; Parse arbitrary text up to a CR. Put chars into data buffer sent to
; the host (pointed to by BX). Called with text of help message in DX
; Return updated pointer in BX and input size in AH
cmtext: mov comand.cmptab,bx ; Save pointer to data buffer. [8 start]
mov cmthlp,dx ; Save the help message
mov cl,0 ; Init the char count
cmtxt1: mov comand.cmsflg,0 ; Get all spaces. [25]
call cmgtch ; Get a char
test ah,80H ; is high-order bit on?
jz cmtxt5 ; Nope, put into the buffer
and ah,07FH
cmp ah,' '
je cmtxt5
cmp ah,esc ; An escape?
jne cmtxt2
mov ah,conout
mov dl,bell ; Ring a bell
int dos
mov comand.cmaflg,0 ; Reset action flag
dec comand.cmcptr ; Move pointer to before the escape
dec comand.cmdptr
dec comand.cmccnt ; Decrement count
jmp cmtxt1 ; Try again
cmtxt2: cmp ah,'?' ; Asking a question?
jz cmtx30
cmp ah,ff ; Formfeed?
jne cmtx2x
call cmblnk
cmtx2x: mov ah,cl ; Return count in AH
mov bx,comand.cmptab ; Return updated pointer
jmp rskp
cmtx30: mov comand.cmaflg,0 ; Reset action flag to zero
inc comand.cmdptr ; count the ?
cmp cl,0 ; Is "?" first char?
jne cmtxt5 ; No, just add to buffer
mov ah,prstr ; Else, give some help
mov dx,cmthlp ; Address of help message
int dos
mov ah,prstr
mov dx,offset crlf ; Print a crlf
int dos
mov ah,prstr
mov dx,comand.cmprmp ; Reprint the prompt
int dos
dec comand.cmcptr ; Don't keep it in the buffer
dec comand.cmccnt ; Don't conut it
dec comand.cmdptr ; don't count if printing help
mov bx,comand.cmdptr ; Get the pointer into the buffer
mov byte ptr [bx],'$'
mov ah,prstr
mov dx,offset comand.cmdbuf ;[fjj] RE-display command buffer
int dos ; [fjj] AFTER adjusting pointers!!!
jmp cmtxt1 ; And keep going
cmtxt5: inc cl ; Increment the count
mov bx,comand.cmptab ; Pointer into destination array
mov [bx],ah ; Put char into the buffer
inc bx
mov comand.cmptab,bx
jmp cmtxt1 ; [8 end]
cmgetc: cmp taklev,0
jne cmget1
jmp cmge10 ; no take file, get from keyboard
cmget1: push bx
push si
mov bx,takadr
mov ax,[bx].takcnt
or ax,[bx].takcnt+2
jnz cmget5
cmget2: mov al,byte ptr [bx].takfcb ; get first byte of fcb
cmp al,0ffh ; is it really a macro?
je cmget4 ; yes, better not try to close it
cmp al,0feh ; or maybe a file handle?
je cmget3 ; yes, close w/2.0 call
mov ah,closf
lea dx,[bx].takfcb
int dos
jmp short cmget4 ; skip over alternate close
cmget3: mov bx,word ptr [bx].takfcb+1 ; this is where file handle is stored
mov ah,close2 ; use 2.0 close
int dos
cmget4: dec taklev
sub takadr,size takinfo
pop si
pop bx
mov al,cr ; end with carriage return..
ret
cmget5: cmp [bx].takchl,0 ; Any chars left in buffer?
jne cmget6
call takrd
cmget6: dec [bx].takchl
sub [bx].takcnt,1 ; DEC doesn't set carry!!
sbb [bx].takcnt+2,0
mov si,[bx].takptr
lodsb
mov [bx].takptr,si
cmp al,ctlz ; maybe control-z?
je cmget2 ; yes, close take file (has to be before pops)
pop si
pop bx
cmp al,lf ; linefeed?
jne cmget7
cmp flags.takflg,0
je cmgetc ; yes, ignore it
cmget7:
cmp flags.takflg,0 ; Echo contents of take file?
je cmget8
push dx
mov dl,al
mov ah,conout
int dos
pop dx
cmget8: ret ; else just return..
cmge10: cmp In_menu_mode, 0 ; Are we in menu mode?
je KER_1 ; No
; In menu mode and not reading from a take file, so it must be time
; to redisplay the menu ..
call Quick_menu ; Display the menu
nop
nop
nop
mov ah, PrStr ; Type string
mov dx, OFFSET CrLf ; CRLF
int Dos ; Makes screen look nicer
jmp CmGetC ; Go get the first character from the newly
; created Pseudo-Macro
KER_1: cmp PC_Type, 2 ; Running on a DEC Rainbow
jNE IBMpcs ; No - skip Rainbow code
; Machine-specific code for DEC Rainbow
cmge10_b:
push es ; Firmware eats this one
Mov di, 6
Int 18h ; Get level 1 char
pop es ; Restore register
cmp cl, 0ffh ; Did we get a char?
jE Check_for_DO ; Yes - go check it
cmp cl, 0 ; No -
jE cmge10_b ; keep looking for one
cmp cl, 1 ; Level 2 char around? (probably type-ahead)
jE IBMpcs ; Yes - go handle it
jmp cmge10_b ; No - we've checked all possibilities,
; something fishy goin' on - try again
Check_for_DO:
test ah, 1 ; Function flag on?
jZ No_DO ; No - this can't be the DO key
cmp al, 1 ; Yes -
; but is this really the DO key?
jE Quick_Term ; Yes - it was the DO key, go into
; terminal emulation mode
; No - some other function key was pressed
Call Check_for_sensible_func_keys ; If Keypad number or '-', ','
; '.', or ENTER
; translate to sensible scan code
jmp No_DO ; If normal return, a sensible key was found
Call Beep ; Else if skip return some nonsensible
; function key was pressed - make a beep
jmp cmge10_b ; and try again
Quick_Term:
mov ah, PrStr ; Code to type a string
mov dx, OFFSET DO_str ; Mark that the user hit the DO key
int Dos
jmp Enter_TE_mode ; Enter Terminal Emulation mode
No_DO: mov ah, coninq ; Make it look like a generic DOS function call
jmp cmge11_A0 ; and join common code with char in al
; Assume at this point that we are an IBM PC or close clone
IBMpcs: mov ah,coninq ; Get a char
cmp flags.debug,0 ; in debug mode?
je cmge11 ; yes, go on
mov ah,8 ; else use read that recognizes ^C
cmge11: int dos
cmge11_A0:
push ax ; save the char
; See if what we have is a special character
or al, al ; Is this char a zero?
jnz cmge11_a ; No, continue
mov ah, 8 ; Get another char
int dos ; to see what we really got the first time
; Maybe quick entry into Terminal Emulation mode
cmp al, 63 ; Is it the code for F5?
je Is_F5 ; Yes
cmp al, 108 ; Is it the code for ALT F5?
je Is_F5 ; Yes
cmp al, 110 ; ALT F7 (exit) ?
je Is_ALT_F7 ; Yes
cmp al, 111 ; ALT F8 (push) ?
je Is_ALT_F8 ; Yes
jmp Ignore_key ; Not a key we work with
Is_F5: mov ah, PrStr ; Code to type a string
mov dx, OFFSET F5_str ; Mark that the user hit the F5 key
int Dos
Enter_TE_mode:
mov sp, OldStk ; Pick up the value SP had before COMND
; was called
mov ax, OFFSET KrmRet ; The return addr that would have been set
push ax ; Put it on the stack
jmp Telnet2 ; Jump quickly into terminal emulation mode
Is_ALT_F7:
mov sp, OldStk ; Pick up the value SP had before COMND
; was called
mov flags.extflg, 0FFh ; Flag that we are leaving
mov ax, OFFSET KrmRet ; The return addr that would have been set
push ax ; Put it on the stack
jmp RSkp ; Exit the program
Is_ALT_F8:
mov sp, OldStk ; Pick up the value SP had before COMND
; was called
mov ax, OFFSET KrmRet ; The return addr that would have been set
push ax ; Put it on the stack
jmp Quick_Push ; Push out of the program
Ignore_key:
pop ax ; Fix up stack
jmp cmge10 ; Then go get a new key
cmge11_a:
cmp al,bs ; backspace?
je cmge13 ; yes, skip echo
cmp al,' ' ; printable?
jae cmge12 ; yes, no translation needed
cmp al,cr ; this is printable
jne cmge11_b
mov dl, al ; Hit CR, first echo it
mov ah, conout
int Dos
mov al, Lf ; Then type a LF
jmp SHORT cmge12
cmge11_b:
cmp al,lf
je cmge12
cmp al,tab
je cmge12
mov al,' ' ; else echo a space
cmge12: mov dl,al ; put char here
mov ah,conout
int dos ; echo it ourselves..
cmge13: pop ax ; and return it
cmp al,'C'-40H ; control-C?
je cmge15 ; yes, go handle
cmp al,tab
jne cmge14
mov al,' '
cmge14: ret
PUBLIC cmge15
cmge15: mov dx,offset ctcmsg
mov ah,prstr
int dos
mov flags.cxzflg,'C' ; remember ^C'd
mov sp,cmdstk ; restore command stack ptr
ret ; and fail
; Come here is user types ^W when during input
cntrlw: mov ah,prstr
mov dx,offset escspc
int dos
dec comand.cmccnt ; Don't include it in the count
dec comand.cmcptr ; Back up past the ^W
mov cl,comand.cmccnt
mov ch,0
jcxz ctlw2
pushf
push es
std ; Scan backwards
mov ax,ds
mov es,ax ; Point to the data area
mov di,comand.cmcptr ; Looking from here
dec di
mov al,' '
repe scasb ; Look for non-space
je ctlw1 ; All spaces, nothing else to do
inc di ; move back to non-space
inc cx
repne scasb ; look for a space
jne ctlw1 ; no space, leave ptrs alone
inc di
inc cx ; skip back over space
ctlw1: inc di
mov comand.cmccnt,cl ; update count
mov cx,comand.cmcptr ; remember old ptr
mov comand.cmcptr,di ; update pointer
sub cx,di ; this is characters moved
mov al,bs ; backspace
cld
mov di,offset tbuff ; temporary buffer
rep stosb ; put enough spaces in
mov byte ptr [di],'$' ; end buffer
mov dx,offset tbuff
mov ah,prstr
int dos ; back up cursor
call clearl ; clear line
pop es
popf
ret ; and return
ctlw2: mov ah,conout
mov dl,bell
int dos
ret
cminbf: push dx
push bx
mov cx,dx ; Save value here too
mov ah,comand.cmaflg ; Is the action char flag set?
cmp ah,0
je cminb1
jmp cminb9 ; If so get no more chars
cminb1: inc comand.cmccnt ; Increment the char count
call cmgetc
mov ah,al ; Keep char in 'ah'
mov bx,comand.cmcptr ; Get the pointer into the buffer
mov [bx],ah ; Put it in the buffer
inc bx
mov comand.cmcptr,bx
cmp ah,'W'-64 ; Is it a ^W?
jne cmnb11
call cntrlw ; Kill the previous word
jmp repars
cmnb11: cmp ah,25O ; Is it a ^U?
jne cminb2
cmnb12: call ctlu ; Clear out the line
mov ah,prstr
mov dx,comand.cmprmp ; Print the prompt
int dos
mov bx,offset comand.cmdbuf
mov comand.cmcptr,bx ; Reset the point to the start
mov comand.cmccnt,0 ; Zero the count
mov dx,cx ; Preserve original value of dx
jmp repars ; Go start over
cminb2: cmp ah,bs ; Or backspace?
jz cminb3
cmp ah,del ; Delete?
jne cminb4
cminb3: call dodel ; Delete a character
mov ah,comand.cmccnt ; Decrement the char count by two
dec ah
dec ah
cmp ah,0 ; Have we gone too far?
jns cmnb32 ; If not proceed
mov ah,conout ; Ring the bell
mov dl,bell
int dos
jmp cmnb12 ; Go reprint prompt and reparse
cmnb32: mov comand.cmccnt,ah ; Save the new char count
mov ah,prstr ; Erase the character
mov dx,offset clrspc
int dos
mov bx,comand.cmcptr ; Get the pointer into the buffer
dec bx ; Back up in the buffer
dec bx
mov comand.cmcptr,bx
jmp repars ; Go reparse everything
cminb4: cmp ah,'?' ; Is it a question mark
jz cminb6
cmp ah,esc ; Is it an escape?
jz cminb8
cmp ah,cr ; Is it a carriage return?
jz cminb5
cmp ah,lf ; Is it a line feed?
jz cminb5
cmp ah,ff ; Is it a formfeed?
jne cminb7
call cmblnk
call locate
cminb5: mov ah,comand.cmccnt ; Have we parsed any chars yet?
cmp ah,1
jnz cminb6
jmp prserr ; If not, just start over
cminb6: mov ah,0FFH ; Set the action flag
mov comand.cmaflg,ah
jmp cminb9
; Got a non-action char, see if it would be the last in the buffer .
; If so, we trash it and beep, since we need to get an action char and
; there wouldn't be room for it otherwise
cminb7: mov ah, comand.cmccnt ; Get current char count
cmp ah, cmdlen-1 ; Max'ed out?
jnl cminb71 ; Yeah, bomb it
jmp cminb1 ; No sweat, go get another
cminb71:
dec comand.cmccnt ; About to blow buffer, back up by 1 char
dec comand.cmcptr ; Back up ptr too .
mov ah, PrStr ; Print the string
mov dx, OFFSET ESCSpc ; String containing BS, space, BS
int DOS
mov ah, conout ; Then ring the bell
mov dl,bell
int DOS
jmp cminb1 ; Get another char
cminb8: mov ah,prstr ; Don't print the escape char
mov dx,offset escspc
int dos
jmp cminb6
cminb9: pop bx
pop dx
ret
cmgtch: push cx
push bx
push dx
cmgtc1: mov ah,comand.cmaflg
cmp ah,0 ; Is it set
jne cmgt10
call cminbf ; If the action char flag is not set get more
cmgt10: mov bx,comand.cmdptr ; Get a pointer into the buffer
mov ah,[bx] ; Get the next char
inc bx
mov comand.cmdptr,bx
cmp ah,' ' ; Is it a space?
jz cmgtc2
cmp ah,tab ; Or a tab?
jne cmgtc3
cmgtc2: mov ah,comand.cmsflg ; Get the space flag
cmp ah,0 ; Was the last char a space?
jne cmgtc1 ; Yes, get another char
mov ah,0FFH ; Set the space flag
mov comand.cmsflg,ah
mov ah,' '
pop dx
pop bx
jmp cmgtc5
cmgtc3: mov al,0
mov comand.cmsflg,al ; Zero the space flag
pop dx
pop bx
cmp ah,esc
jz cmgtc5
cmp ah,'?' ; Is the user curious?
jz cmgtc4
cmp ah,cr
jz cmgtc4
cmp ah,lf
jz cmgtc4
cmp ah,ff
je cmgtc4
pop cx
ret ; Not an action char, just return
cmgtc4: dec comand.cmdptr
cmgtc5: or ah,80H ; Make the char negative to indicate
pop cx
ret ; it is a terminator
CMND ENDP
; This address is jumped to on reparse
PARSE PROC NEAR
repars: mov sp,comand.cmostp ; new sp <-- old sp
mov bx,offset comand.cmdbuf
mov comand.cmdptr,bx
mov ah,0FFH
mov comand.cmsflg,ah
jmp comand.cmrprs ; go back to reparse address
; This address can be jumped to on a parsing error
prserr: mov sp,comand.cmostp ; Set new sp to old one
mov bx,offset comand.cmdbuf
mov comand.cmcptr,bx ; Initialize the command pointer
mov comand.cmdptr,bx
mov ah,0
mov comand.cmaflg,ah ; Zero the flags
mov comand.cmccnt,ah
mov comand.cmsflg,0FFH
cmp taklev,0 ; in take cmd?
jne prser1 ; yes, don't print prompt
mov ah,prstr ; Print the prompt
mov dx,comand.cmprmp ; Get the prompt
int dos
; Instead return to before the prompt call
prser1: jmp comand.cmrprs
PARSE ENDP
; FCB must be remembered if found "*" in filename. [7 start]
; Copy from place addressed by BX to place addressed by DI
; Also use to get the filename to the FCB from the DTA
FCBCPY PROC NEAR
push es
push si
mov ax,ds
mov es,ax ; make sure destination segment is correct
mov ch,0 ; high-order part of length
jcxz fcbcp1 ; zero argument (is this necessary???)
mov si,bx ; this is source
rep movsb ; copy the whole thing
fcbcp1: pop si
pop es
ret ; and return
FCBCPY ENDP
; Rainbow-specific routine --
;
; During command screen input, the user may hit a keypad key desiring a
; certain number or a DASH, COMMA, PERIOD or ENTER
; Since these are 'function keys' they have strange scan codes instead of
; the correct ASCII codes - we fix 'em up here
Check_for_sensible_func_keys PROC NEAR
Cld ; Set direction to from Left-to-Right
Mov cx, Func_table_length ; Length of translate table
Mov di, OFFSET Sensible_func_keys ; Address of lookup table
RepNE ScasB ; Look for function key value
jE Found ; Found it!
jmp Rskp ; Didn't find it - skip return
; If found translate to correct ASCII code
Found: Dec di ; Make di point to found entry
Sub di, OFFSET Sensible_func_keys ; Turn address into array dimension
Mov al, To_ASCII_scan_codes[di] ; Translate function key to ASCII
Ret ; and return
Check_for_sensible_func_keys ENDP
; Jumping to this location is like retskp. It assumes the instruction
; after the call is a jmp addr
RSKP PROC NEAR
pop bp
add bp,3
push bp
; ret
RSKP ENDP
; Jumping here is the same as a ret
R PROC NEAR
ret
R ENDP
Code ENDS
END